[[...path]].page.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. import React from 'react';
  2. import { isClient } from '@growi/core';
  3. import {
  4. NextPage, GetServerSideProps, GetServerSidePropsContext,
  5. } from 'next';
  6. import { useTranslation } from 'next-i18next';
  7. import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
  8. import dynamic from 'next/dynamic';
  9. import { useRouter } from 'next/router';
  10. import { Container, Provider } from 'unstated';
  11. import AdminAppContainer from '~/client/services/AdminAppContainer';
  12. import AdminBasicSecurityContainer from '~/client/services/AdminBasicSecurityContainer';
  13. import AdminCustomizeContainer from '~/client/services/AdminCustomizeContainer';
  14. import AdminExternalAccountsContainer from '~/client/services/AdminExternalAccountsContainer';
  15. import AdminGeneralSecurityContainer from '~/client/services/AdminGeneralSecurityContainer';
  16. import AdminGitHubSecurityContainer from '~/client/services/AdminGitHubSecurityContainer';
  17. import AdminGoogleSecurityContainer from '~/client/services/AdminGoogleSecurityContainer';
  18. import AdminHomeContainer from '~/client/services/AdminHomeContainer';
  19. import AdminImportContainer from '~/client/services/AdminImportContainer';
  20. import AdminLdapSecurityContainer from '~/client/services/AdminLdapSecurityContainer';
  21. import AdminLocalSecurityContainer from '~/client/services/AdminLocalSecurityContainer';
  22. import AdminMarkDownContainer from '~/client/services/AdminMarkDownContainer';
  23. import AdminNotificationContainer from '~/client/services/AdminNotificationContainer';
  24. import AdminOidcSecurityContainer from '~/client/services/AdminOidcSecurityContainer';
  25. import AdminSamlSecurityContainer from '~/client/services/AdminSamlSecurityContainer';
  26. import AdminSlackIntegrationLegacyContainer from '~/client/services/AdminSlackIntegrationLegacyContainer';
  27. import AdminTwitterSecurityContainer from '~/client/services/AdminTwitterSecurityContainer';
  28. import AdminUserGroupDetailContainer from '~/client/services/AdminUserGroupDetailContainer';
  29. import AdminUsersContainer from '~/client/services/AdminUsersContainer';
  30. import { CrowiRequest } from '~/interfaces/crowi-request';
  31. import PluginUtils from '~/server/plugins/plugin-utils';
  32. import ConfigLoader from '~/server/service/config-loader';
  33. import {
  34. useCurrentUser, /* useSearchServiceConfigured, */ useIsAclEnabled, useIsMailerSetup, useIsSearchServiceReachable, useSiteUrl,
  35. } from '~/stores/context';
  36. import {
  37. CommonProps, getServerSideCommonProps, useCustomTitle, getNextI18NextConfig,
  38. } from '../utils/commons';
  39. // import { useEnvVars } from '~/stores/admin-context';
  40. const AdminHome = dynamic(() => import('../../components/Admin/AdminHome/AdminHome'), { ssr: false });
  41. const AppSettingsPageContents = dynamic(() => import('../../components/Admin/App/AppSettingsPageContents'), { ssr: false });
  42. const SecurityManagementContents = dynamic(() => import('../../components/Admin/Security/SecurityManagementContents'), { ssr: false });
  43. const MarkDownSettingContents = dynamic(() => import('../../components/Admin/MarkdownSetting/MarkDownSettingContents'), { ssr: false });
  44. const CustomizeSettingContents = dynamic(() => import('../../components/Admin/Customize/Customize'), { ssr: false });
  45. const DataImportPageContents = dynamic(() => import('../../components/Admin/ImportData/ImportDataPageContents'), { ssr: false });
  46. const ExportArchiveDataPage = dynamic(() => import('../../components/Admin/ExportArchiveDataPage'), { ssr: false });
  47. const NotificationSetting = dynamic(() => import('../../components/Admin/Notification/NotificationSetting'), { ssr: false });
  48. const SlackIntegration = dynamic(() => import('../../components/Admin/SlackIntegration/SlackIntegration'), { ssr: false });
  49. const LegacySlackIntegration = dynamic(() => import('../../components/Admin/LegacySlackIntegration/LegacySlackIntegration'), { ssr: false });
  50. const UserManagement = dynamic(() => import('../../components/Admin/UserManagement'), { ssr: false });
  51. const ManageExternalAccount = dynamic(() => import('../../components/Admin/ManageExternalAccount'), { ssr: false });
  52. const UserGroupPage = dynamic(() => import('../../components/Admin/UserGroup/UserGroupPage'), { ssr: false });
  53. const ElasticsearchManagement = dynamic(() => import('../../components/Admin/ElasticsearchManagement/ElasticsearchManagement'), { ssr: false });
  54. // named export
  55. const AuditLogManagement = dynamic(() => import('../../components/Admin/AuditLogManagement').then(module => module.AuditLogManagement));
  56. const AdminLayout = dynamic(() => import('../../components/Layout/AdminLayout'), { ssr: false });
  57. const pluginUtils = new PluginUtils();
  58. type Props = CommonProps & {
  59. currentUser: any,
  60. nodeVersion: string,
  61. npmVersion: string,
  62. yarnVersion: string,
  63. installedPlugins: any,
  64. envVars: any,
  65. isAclEnabled: boolean,
  66. isSearchServiceConfigured: boolean,
  67. isSearchServiceReachable: boolean,
  68. isMailerSetup: boolean,
  69. siteUrl: string,
  70. };
  71. const AdminMarkdownSettingsPage: NextPage<Props> = (props: Props) => {
  72. const { t } = useTranslation('admin');
  73. const router = useRouter();
  74. const { path } = router.query;
  75. const pagePathKeys: string[] = Array.isArray(path) ? path : ['home'];
  76. const adminPagesMap = {
  77. home: {
  78. title: useCustomTitle(props, t('Wiki Management Home Page')),
  79. component: <AdminHome
  80. nodeVersion={props.nodeVersion}
  81. npmVersion={props.npmVersion}
  82. yarnVersion={props.yarnVersion}
  83. installedPlugins={props.installedPlugins}
  84. />,
  85. },
  86. app: {
  87. title: useCustomTitle(props, t('App Settings')),
  88. component: <AppSettingsPageContents />,
  89. },
  90. security: {
  91. title: useCustomTitle(props, t('security_settings')),
  92. component: <SecurityManagementContents />,
  93. },
  94. markdown: {
  95. title: useCustomTitle(props, t('Markdown Settings')),
  96. component: <MarkDownSettingContents />,
  97. },
  98. customize: {
  99. title: useCustomTitle(props, t('Customize Settings')),
  100. component: <CustomizeSettingContents />,
  101. },
  102. importer: {
  103. title: useCustomTitle(props, t('Import Data')),
  104. component: <DataImportPageContents />,
  105. },
  106. export: {
  107. title: useCustomTitle(props, t('Export Archive Data')),
  108. component: <ExportArchiveDataPage />,
  109. },
  110. notification: {
  111. title: useCustomTitle(props, t('Notification Settings')),
  112. component: <NotificationSetting />,
  113. },
  114. 'global-notification': {
  115. title: '',
  116. component: <>global-notification</>,
  117. },
  118. 'slack-integration': {
  119. title: useCustomTitle(props, t('slack_integration')),
  120. component: <SlackIntegration />,
  121. },
  122. 'slack-integration-legacy': {
  123. title: useCustomTitle(props, t('Legacy_Slack_Integration')),
  124. component: <LegacySlackIntegration />,
  125. },
  126. users: {
  127. title: useCustomTitle(props, t('User_Management')),
  128. component: <UserManagement />,
  129. 'external-accounts': {
  130. title: useCustomTitle(props, t('external_account_management')),
  131. component: <ManageExternalAccount />,
  132. },
  133. },
  134. 'user-groups': {
  135. title: useCustomTitle(props, t('UserGroup Management')),
  136. component: <UserGroupPage />,
  137. },
  138. search: {
  139. title: useCustomTitle(props, t('Full Text Search Management')),
  140. component: <ElasticsearchManagement />,
  141. },
  142. 'audit-log': {
  143. title: useCustomTitle(props, t('AuditLog')),
  144. component: <AuditLogManagement />,
  145. },
  146. };
  147. const getTargetPageToRender = (pagesMap, keys) => {
  148. return keys.reduce((pagesMap, key) => {
  149. return pagesMap[key];
  150. }, pagesMap);
  151. };
  152. const targetPage: {title: string, component: JSX.Element} = getTargetPageToRender(adminPagesMap, pagePathKeys);
  153. const title = targetPage.title;
  154. useCurrentUser(props.currentUser != null ? JSON.parse(props.currentUser) : null);
  155. useIsMailerSetup(props.isMailerSetup);
  156. // useSearchServiceConfigured(props.isSearchServiceConfigured);
  157. useIsSearchServiceReachable(props.isSearchServiceReachable);
  158. useIsAclEnabled(props.isAclEnabled);
  159. useSiteUrl(props.siteUrl);
  160. // useEnvVars(props.envVars);
  161. const injectableContainers: Container<any>[] = [];
  162. if (isClient()) {
  163. // Create unstated container instances (except Security)
  164. const adminAppContainer = new AdminAppContainer();
  165. const adminImportContainer = new AdminImportContainer();
  166. const adminHomeContainer = new AdminHomeContainer();
  167. const adminCustomizeContainer = new AdminCustomizeContainer();
  168. const adminUsersContainer = new AdminUsersContainer();
  169. const adminExternalAccountsContainer = new AdminExternalAccountsContainer();
  170. const adminNotificationContainer = new AdminNotificationContainer();
  171. const adminSlackIntegrationLegacyContainer = new AdminSlackIntegrationLegacyContainer();
  172. const adminMarkDownContainer = new AdminMarkDownContainer();
  173. const adminUserGroupDetailContainer = new AdminUserGroupDetailContainer();
  174. injectableContainers.push(
  175. adminAppContainer,
  176. adminImportContainer,
  177. adminHomeContainer,
  178. adminCustomizeContainer,
  179. adminUsersContainer,
  180. adminExternalAccountsContainer,
  181. adminNotificationContainer,
  182. adminSlackIntegrationLegacyContainer,
  183. adminMarkDownContainer,
  184. adminUserGroupDetailContainer,
  185. );
  186. }
  187. const adminSecurityContainers: Container<any>[] = [];
  188. if (isClient()) {
  189. const adminSecuritySettingElem = document.getElementById('admin-security-setting');
  190. if (adminSecuritySettingElem != null) {
  191. // Create unstated container instances (Security)
  192. const adminGeneralSecurityContainer = new AdminGeneralSecurityContainer();
  193. const adminLocalSecurityContainer = new AdminLocalSecurityContainer();
  194. const adminLdapSecurityContainer = new AdminLdapSecurityContainer();
  195. const adminSamlSecurityContainer = new AdminSamlSecurityContainer();
  196. const adminOidcSecurityContainer = new AdminOidcSecurityContainer();
  197. const adminBasicSecurityContainer = new AdminBasicSecurityContainer();
  198. const adminGoogleSecurityContainer = new AdminGoogleSecurityContainer();
  199. const adminGitHubSecurityContainer = new AdminGitHubSecurityContainer();
  200. const adminTwitterSecurityContainer = new AdminTwitterSecurityContainer();
  201. adminSecurityContainers.push(
  202. adminGeneralSecurityContainer,
  203. adminLocalSecurityContainer,
  204. adminLdapSecurityContainer,
  205. adminSamlSecurityContainer,
  206. adminOidcSecurityContainer,
  207. adminBasicSecurityContainer,
  208. adminGoogleSecurityContainer,
  209. adminGitHubSecurityContainer,
  210. adminTwitterSecurityContainer,
  211. );
  212. }
  213. }
  214. return (
  215. <Provider inject={[...injectableContainers, ...adminSecurityContainers]}>
  216. <AdminLayout title={title} selectedNavOpt={pagePathKeys[0]}>
  217. {targetPage.component}
  218. </AdminLayout>
  219. </Provider>
  220. );
  221. };
  222. function injectServerConfigurations(context: GetServerSidePropsContext, props: Props): void {
  223. const req: CrowiRequest = context.req as CrowiRequest;
  224. const { crowi } = req;
  225. const { mailService } = crowi;
  226. props.isMailerSetup = mailService.isMailerSetup;
  227. }
  228. /**
  229. * for Server Side Translations
  230. * @param context
  231. * @param props
  232. * @param namespacesRequired
  233. */
  234. async function injectNextI18NextConfigurations(context: GetServerSidePropsContext, props: Props, namespacesRequired?: string[] | undefined): Promise<void> {
  235. const nextI18NextConfig = await getNextI18NextConfig(serverSideTranslations, context, namespacesRequired);
  236. props._nextI18Next = nextI18NextConfig._nextI18Next;
  237. }
  238. export const getServerSideProps: GetServerSideProps = async(context: GetServerSidePropsContext) => {
  239. const req: CrowiRequest = context.req as CrowiRequest;
  240. const { crowi } = req;
  241. const {
  242. appService, searchService, aclService,
  243. } = crowi;
  244. const { user } = req;
  245. const result = await getServerSideCommonProps(context);
  246. // check for presence
  247. // see: https://github.com/vercel/next.js/issues/19271#issuecomment-730006862
  248. if (!('props' in result)) {
  249. throw new Error('invalid getSSP result');
  250. }
  251. const props: Props = result.props as Props;
  252. if (user != null) {
  253. // props.currentUser = JSON.stringify(user.toObject());
  254. props.currentUser = JSON.stringify(user);
  255. }
  256. injectServerConfigurations(context, props);
  257. injectNextI18NextConfigurations(context, props, ['admin']);
  258. props.siteUrl = appService.getSiteUrl();
  259. props.nodeVersion = crowi.runtimeVersions.versions.node ? crowi.runtimeVersions.versions.node.version.version : null;
  260. props.npmVersion = crowi.runtimeVersions.versions.npm ? crowi.runtimeVersions.versions.npm.version.version : null;
  261. props.yarnVersion = crowi.runtimeVersions.versions.yarn ? crowi.runtimeVersions.versions.yarn.version.version : null;
  262. props.installedPlugins = pluginUtils.listPlugins();
  263. props.envVars = await ConfigLoader.getEnvVarsForDisplay(true);
  264. props.isAclEnabled = aclService.isAclEnabled();
  265. props.isSearchServiceConfigured = searchService.isConfigured;
  266. props.isSearchServiceReachable = searchService.isReachable;
  267. return {
  268. props,
  269. };
  270. };
  271. export default AdminMarkdownSettingsPage;